
#include "spi_flash.h"
#include "log.h"
#ifdef USE_SPI

void _spi_flash_Init(SPI_FLASH *spi_flash);
static uint16_t  _spi_flash_ReadID(SPI_FLASH *spi_flash);  	    		//读取FLASH ID
static uint8_t _spi_flash_ReadSR(SPI_FLASH *spi_flash,uint8_t regno);             //读取状态寄存器 
static void _spi_flash_Write_SR(SPI_FLASH *spi_flash,uint16_t sr) ;   //写状态寄存器
static void _spi_flash_Write_Enable(SPI_FLASH *spi_flash);  		//写使能 
static void _spi_flash_Write_Disable(SPI_FLASH *spi_flash);		//写保护
static void _spi_flash_Write_NoCheck(SPI_FLASH *spi_flash,uint8_t* pBuffer,uint32_t WriteAddr,uint32_t NumByteToWrite);
void _spi_flash_Read(SPI_FLASH *spi_flash,uint8_t* pBuffer,uint32_t ReadAddr,uint32_t NumByteToRead);   //读取flash
void _spi_flash_Write(SPI_FLASH *spi_flash,uint8_t* pBuffer,uint32_t WriteAddr,uint32_t NumByteToWrite);//写入flash

void _spi_flash_Quad_Write_Page(SPI_FLASH *spi_flash,uint8_t* pBuffer,uint32_t WriteAddr,uint32_t NumByteToWrite);
void _spi_flash_Quad_Read(SPI_FLASH *spi_flash,uint8_t* pBuffer,uint32_t ReadAddr,uint32_t NumByteToRead);
  
void _spi_flash_Erase_Chip(SPI_FLASH *spi_flash);    	  	//整片擦除
void _spi_flash_Erase_Sector(SPI_FLASH *spi_flash,uint32_t Dst_Addr);	//扇区擦除
static void _spi_flash_Wait_Busy(SPI_FLASH *spi_flash);           	//等待空闲
void _spi_flash_PowerDown(SPI_FLASH *spi_flash);        	//进入掉电模式
void _spi_flash_WAKEUP(SPI_FLASH *spi_flash);				//唤醒


//4Kbytes为一个Sector
//16个扇区为1个Block
//W25Q256
//容量为32M字节,共有512个Block,8192个Sector 
		
//初始化SPI FLASH的IO口
void _spi_flash_Init(SPI_FLASH *spi_flash)
{ 
		uint16_t temp;
		spi_flash->cs.set_bit(&spi_flash->cs);			                //SPI FLASH不选中
		spi_flash->spi.SetSpeed(&spi_flash->spi,SPI_PSC_2); //设置为60M时钟,高速模式
		spi_flash->flash_type=_spi_flash_ReadID(spi_flash);	        //读取FLASH ID.
		log_info("Flash ID is 0x%X",spi_flash->flash_type);
    if(spi_flash->flash_type==W25Q256)                    //SPI FLASH为W25Q256
    {
        temp=_spi_flash_ReadSR(spi_flash,3);              //读取状态寄存器3，判断地址模式
        if((temp&0X01)==0)			        //如果不是4字节地址模式,则进入4字节地址模式
				{
					spi_flash->cs.reset_bit(&spi_flash->cs); 			        //选中
					spi_flash->spi.readwritebyte(&spi_flash->spi,Flash_Enable4ByteAddr);//发送进入4字节地址模式指令   
					spi_flash->cs.set_bit(&spi_flash->cs);       		        //取消片选   
				}
    }
}  

//读取_spi_flash的状态寄存器，_spi_flash一共有3个状态寄存器
//状态寄存器1：
//BIT7  6   5   4   3   2   1   0
//SPR   RV  TB BP2 BP1 BP0 WEL BUSY
//SPR:默认0,状态寄存器保护位,配合WP使用
//TB,BP2,BP1,BP0:FLASH区域写保护设置
//WEL:写使能锁定
//BUSY:忙标记位(1,忙;0,空闲)
//默认:0x00
//状态寄存器2：
//BIT7  6   5   4   3   2   1   0
//SUS   CMP LB3 LB2 LB1 (R) QE  SRP1
//状态寄存器3：
//BIT7      6    5    4   3   2   1   0
//HOLD/RST  DRV1 DRV0 (R) (R) WPS ADP ADS
//regno:状态寄存器号，范:1~3
//返回值:状态寄存器值
static uint8_t _spi_flash_ReadSR(SPI_FLASH *spi_flash,uint8_t regno)   
{  
	uint8_t byte=0,command=0; 
    switch(regno)
    {
        case 1:
            command=Flash_ReadStatusReg1;    //读状态寄存器1指令
            break;
        case 2:
            command=Flash_ReadStatusReg2;    //读状态寄存器2指令
            break;
        case 3:
            command=Flash_ReadStatusReg3;    //读状态寄存器3指令
            break;
        default:
            command=Flash_ReadStatusReg1;    
            break;
    }    
	spi_flash->cs.reset_bit(&spi_flash->cs);                            //使能器件   
	spi_flash->spi.readwritebyte(&spi_flash->spi,command);            //发送读取状态寄存器命令    
	byte=spi_flash->spi.readwritebyte(&spi_flash->spi,0Xff);          //读取一个字节  
	spi_flash->cs.set_bit(&spi_flash->cs);                            //取消片选     
	return byte;   
} 

//写_spi_flash状态寄存器
static void _spi_flash_Write_SR(SPI_FLASH *spi_flash,uint16_t sr)   
{   
	spi_flash->cs.reset_bit(&spi_flash->cs);                            //使能器件   
	spi_flash->spi.readwritebyte(&spi_flash->spi,Flash_WriteStatusReg1);            //发送写取状态寄存器命令    
	spi_flash->spi.readwritebyte(&spi_flash->spi,sr&0xFF);                 //写入一个字节
	spi_flash->spi.readwritebyte(&spi_flash->spi,(sr>>8)&0xFF);                 //写入一个字节    
	spi_flash->cs.set_bit(&spi_flash->cs);                            //取消片选     	      
}   
//W25QXX写使能	
//将WEL置位   
static void _spi_flash_Write_Enable(SPI_FLASH *spi_flash)   
{
	spi_flash->cs.reset_bit(&spi_flash->cs);                            //使能器件   
	spi_flash->spi.readwritebyte(&spi_flash->spi,Flash_WriteEnable);   //发送写使能  
	spi_flash->cs.set_bit(&spi_flash->cs);                            //取消片选     	      
} 
//_spi_flash写禁止	
//将WEL清零  
static void _spi_flash_Write_Disable(SPI_FLASH *spi_flash)   
{  
	spi_flash->cs.reset_bit(&spi_flash->cs);                            //使能器件   
	spi_flash->spi.readwritebyte(&spi_flash->spi,Flash_WriteDisable);  //发送写禁止指令    
	spi_flash->cs.set_bit(&spi_flash->cs);                            //取消片选     	      
} 

//读取芯片ID
//返回值如下:				   
//0XEF13,表示芯片型号为W25Q80  
//0XEF14,表示芯片型号为W25Q16    
//0XEF15,表示芯片型号为W25Q32  
//0XEF16,表示芯片型号为W25Q64 
//0XEF17,表示芯片型号为W25Q128 	  
//0XEF18,表示芯片型号为W25Q256
static uint16_t _spi_flash_ReadID(SPI_FLASH *spi_flash)
{
	uint16_t Temp = 0;	  
	spi_flash->cs.reset_bit(&spi_flash->cs);				    
	spi_flash->spi.readwritebyte(&spi_flash->spi,Flash_ManufactDeviceID);//发送读取ID命令	    
	spi_flash->spi.readwritebyte(&spi_flash->spi,0x00); 	    
	spi_flash->spi.readwritebyte(&spi_flash->spi,0x00); 	    
	spi_flash->spi.readwritebyte(&spi_flash->spi,0x00); 	 			   
	Temp|=spi_flash->spi.readwritebyte(&spi_flash->spi,0xFF)<<8;  
	Temp|=spi_flash->spi.readwritebyte(&spi_flash->spi,0xFF);	 
	spi_flash->cs.set_bit(&spi_flash->cs);				    
	return Temp;
}   
// //4线方式读取芯片ID
// static uint16_t _spi_flash_ReadID_QuadSPI(void)
// {
// 	uint16_t Temp = 0;	  
// 	spi_flash->cs.reset_bit(&spi_flash->cs);				    
// 	spi_flash->spi.readwritebyte(&spi_flash->spi,Flash_ManufactDeviceID_QSPI);//发送读取ID命令
// 	qspi_mode_change(QSPI_MODE);	
// 	Temp =qspi_ReadByte()<<8;  
// 	Temp|=qspi_ReadByte();
// 	log_info("addr is 0x%x",Temp);	    	 			   
// 	Temp =qspi_ReadByte()<<8;  
// 	Temp|=qspi_ReadByte();	
// 	log_info("addr is 0x%x",Temp);
// 	qspi_WriteByte(0xFF);  
// 	qspi_WriteByte(0xFF);
// 	Temp =qspi_ReadByte()<<8;  
// 	Temp|=qspi_ReadByte();	
// 	log_info("id is 0x%x",Temp);
// 	Temp =qspi_ReadByte()<<8;  
// 	Temp|=qspi_ReadByte();	
// 	log_info("id is 0x%x",Temp);	 
// 	Temp =qspi_ReadByte()<<8;  
// 	Temp|=qspi_ReadByte();	
// 	log_info("id is 0x%x",Temp);	 
// 	spi_flash->cs.set_bit(&spi_flash->cs);	
// 	qspi_mode_change(SPI_MODE);			    
// 	return Temp;
// }  		    
//读取SPI FLASH  
//在指定地址开始读取指定长度的数据
//pBuffer:数据存储区
//ReadAddr:开始读取的地址(24bit)
//NumByteToRead:要读取的字节数(最大65535)
static void _spi_flash_Read(SPI_FLASH *spi_flash,uint8_t* pBuffer,uint32_t ReadAddr,uint32_t NumByteToRead)   
{ 
 	uint32_t i;   										    
	spi_flash->cs.reset_bit(&spi_flash->cs);                            //使能器件   
    spi_flash->spi.readwritebyte(&spi_flash->spi,Flash_ReadData);      //发送读取命令  
    if(spi_flash->flash_type==W25Q256)                //如果是W25Q256的话地址为4字节的，要发送最高8位
    {
        spi_flash->spi.readwritebyte(&spi_flash->spi,(uint8_t)((ReadAddr)>>24));    
    }
    spi_flash->spi.readwritebyte(&spi_flash->spi,(uint8_t)((ReadAddr)>>16));   //发送24bit地址    
    spi_flash->spi.readwritebyte(&spi_flash->spi,(uint8_t)((ReadAddr)>>8));   
    spi_flash->spi.readwritebyte(&spi_flash->spi,(uint8_t)ReadAddr);   
    for(i=0;i<NumByteToRead;i++)
	{ 
        pBuffer[i]=spi_flash->spi.readwritebyte(&spi_flash->spi,0XFF);    //循环读数  
    }
	spi_flash->cs.set_bit(&spi_flash->cs);  				    	      
}  

//static void _spi_flash_Quad_Read(SPI_FLASH *spi_flash,uint8_t* pBuffer,uint32_t ReadAddr,uint16_t NumByteToRead)   
// { 
//  	uint16_t i;   										    
// 	spi_flash->cs.reset_bit(&spi_flash->cs);                            //使能器件   
//     spi_flash->spi.readwritebyte(&spi_flash->spi,Flash_FastReadQuad);      //发送读取命令  
//     if(spi_flash->flash_type==W25Q256)                //如果是W25Q256的话地址为4字节的，要发送最高8位
//     {
//         spi_flash->spi.readwritebyte(&spi_flash->spi,(uint8_t)((ReadAddr)>>24));    
//     }
//     spi_flash->spi.readwritebyte(&spi_flash->spi,(uint8_t)((ReadAddr)>>16));   //发送24bit地址    
//     spi_flash->spi.readwritebyte(&spi_flash->spi,(uint8_t)((ReadAddr)>>8));   
//     spi_flash->spi.readwritebyte(&spi_flash->spi,(uint8_t)ReadAddr);  
// 	qspi_mode_change(QSPI_MODE); 
//     for(i=0;i<NumByteToRead;i++)
// 	{ 
//         pBuffer[i]=qspi_ReadByte();    //循环读数  
//     }
// 	spi_flash->cs.set_bit(&spi_flash->cs);  			
// 	qspi_mode_change(SPI_MODE);	    	      
// } 
//SPI在一页(0~65535)内写入少于256个字节的数据
//在指定地址开始写入最大256字节的数据
//pBuffer:数据存储区
//WriteAddr:开始写入的地址(24bit)
//NumByteToWrite:要写入的字节数(最大256),该数不应该超过该页的剩余字节数!!!	 
static void _spi_flash_Write_Page(SPI_FLASH *spi_flash,uint8_t* pBuffer,uint32_t WriteAddr,uint32_t NumByteToWrite)
{
 	uint16_t i;  
    _spi_flash_Write_Enable(spi_flash);                  //SET WEL 
	spi_flash->cs.reset_bit(&spi_flash->cs);                            //使能器件   
    spi_flash->spi.readwritebyte(&spi_flash->spi,Flash_PageProgram);   //发送写页命令   
    if(spi_flash->flash_type==W25Q256)                //如果是W25Q256的话地址为4字节的，要发送最高8位
    {
        spi_flash->spi.readwritebyte(&spi_flash->spi,(uint8_t)((WriteAddr)>>24)); 
    }
    spi_flash->spi.readwritebyte(&spi_flash->spi,(uint8_t)((WriteAddr)>>16)); //发送24bit地址    
    spi_flash->spi.readwritebyte(&spi_flash->spi,(uint8_t)((WriteAddr)>>8));   
    spi_flash->spi.readwritebyte(&spi_flash->spi,(uint8_t)WriteAddr);   
    for(i=0;i<NumByteToWrite;i++)spi_flash->spi.readwritebyte(&spi_flash->spi,pBuffer[i]);//循环写数  
	spi_flash->cs.set_bit(&spi_flash->cs);                            //取消片选 
	_spi_flash_Wait_Busy(spi_flash);					   //等待写入结束
} 

//static void _spi_flash_Quad_Write_Page(SPI_FLASH *spi_flash,uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)
// {
//  	uint16_t i;  
//     _spi_flash_Write_Enable();                  //SET WEL 
// 	spi_flash->cs.reset_bit(&spi_flash->cs);                            //使能器件   
//     spi_flash->spi.readwritebyte(&spi_flash->spi,Flash_QuadWrite);   //发送写页命令   
//     if(spi_flash->flash_type==W25Q256)                //如果是W25Q256的话地址为4字节的，要发送最高8位
//     {
//         spi_flash->spi.readwritebyte(&spi_flash->spi,(uint8_t)((WriteAddr)>>24)); 
//     }
//     spi_flash->spi.readwritebyte(&spi_flash->spi,(uint8_t)((WriteAddr)>>16)); //发送24bit地址    
//     spi_flash->spi.readwritebyte(&spi_flash->spi,(uint8_t)((WriteAddr)>>8));   
//     spi_flash->spi.readwritebyte(&spi_flash->spi,(uint8_t)WriteAddr);   
// 	qspi_mode_change(QSPI_MODE);
//     for(i=0;i<NumByteToWrite;i++)qspi_WriteByte(pBuffer[i]);//循环写数  
// 	spi_flash->cs.set_bit(&spi_flash->cs);                            //取消片选 
// 	qspi_mode_change(SPI_MODE);
// 	_spi_flash_Wait_Busy();					   //等待写入结束
// } 

//无检验写SPI FLASH 
//必须确保所写的地址范围内的数据全部为0XFF,否则在非0XFF处写入的数据将失败!
//具有自动换页功能 
//在指定地址开始写入指定长度的数据,但是要确保地址不越界!
//pBuffer:数据存储区
//WriteAddr:开始写入的地址(24bit)
//NumByteToWrite:要写入的字节数(最大65535)
//CHECK OK
static void _spi_flash_Write_NoCheck(SPI_FLASH *spi_flash,uint8_t* pBuffer,uint32_t WriteAddr,uint32_t NumByteToWrite)   
{ 			 		 
	uint16_t pageremain;	   
	pageremain=256-WriteAddr%256; //单页剩余的字节数		 	    
	if(NumByteToWrite<=pageremain)pageremain=NumByteToWrite;//不大于256个字节
	while(1)
	{	   
		_spi_flash_Write_Page(spi_flash,pBuffer,WriteAddr,pageremain);
		if(NumByteToWrite==pageremain)break;//写入结束了
	 	else //NumByteToWrite>pageremain
		{
			pBuffer+=pageremain;
			WriteAddr+=pageremain;	

			NumByteToWrite-=pageremain;			  //减去已经写入了的字节数
			if(NumByteToWrite>256)pageremain=256; //一次可以写入256个字节
			else pageremain=NumByteToWrite; 	  //不够256个字节了
		}
	};	    
} 

// void _spi_flash_Quad_Write_NoCheck(SPI_FLASH *spi_flash,uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)   
// { 			 		 
// 	uint16_t pageremain;	   
// 	pageremain=256-WriteAddr%256; //单页剩余的字节数		 	    
// 	if(NumByteToWrite<=pageremain)pageremain=NumByteToWrite;//不大于256个字节
// 	while(1)
// 	{	   
// 		_spi_flash_Quad_Write_Page(pBuffer,WriteAddr,pageremain);
// 		if(NumByteToWrite==pageremain)break;//写入结束了
// 	 	else //NumByteToWrite>pageremain
// 		{
// 			pBuffer+=pageremain;
// 			WriteAddr+=pageremain;	

// 			NumByteToWrite-=pageremain;			  //减去已经写入了的字节数
// 			if(NumByteToWrite>256)pageremain=256; //一次可以写入256个字节
// 			else pageremain=NumByteToWrite; 	  //不够256个字节了
// 		}
// 	};	    
// } 

//写SPI FLASH  
//在指定地址开始写入指定长度的数据
//该函数带擦除操作!
//pBuffer:数据存储区
//WriteAddr:开始写入的地址(24bit)						
//NumByteToWrite:要写入的字节数(最大65535)   
uint8_t FLASH_BUFFER[4096];		 
static void _spi_flash_Write(SPI_FLASH *spi_flash,uint8_t* pBuffer,uint32_t WriteAddr,uint32_t NumByteToWrite)   
{ 
	uint32_t secpos;
	uint16_t secoff;
	uint16_t secremain;	   
 	uint16_t i;    
	uint8_t * flash_buf;	  
   	flash_buf=FLASH_BUFFER;	     
 	secpos=WriteAddr/4096;//扇区地址  
	secoff=WriteAddr%4096;//在扇区内的偏移
	secremain=4096-secoff;//扇区剩余空间大小   
 	log_info("ad:%X,nb:%X\r\n",WriteAddr,NumByteToWrite);//测试用
 	if(NumByteToWrite<=secremain)secremain=NumByteToWrite;//不大于4096个字节
	while(1) 
	{	
		_spi_flash_Read(spi_flash,flash_buf,secpos*4096,4096);//读出整个扇区的内容
		for(i=0;i<secremain;i++)//校验数据
		{
			if(flash_buf[secoff+i]!=0XFF)break;//需要擦除  	  
		}
		if(i<secremain)//需要擦除
		{
			_spi_flash_Erase_Sector(spi_flash,secpos);//擦除这个扇区
			for(i=0;i<secremain;i++)	   //复制
			{
				flash_buf[i+secoff]=pBuffer[i];	  
			}
			_spi_flash_Write_NoCheck(spi_flash,flash_buf,secpos*4096,4096);//写入整个扇区  

		}else _spi_flash_Write_NoCheck(spi_flash,pBuffer,WriteAddr,secremain);//写已经擦除了的,直接写入扇区剩余区间. 				   
		if(NumByteToWrite==secremain)break;//写入结束了
		else//写入未结束
		{
			secpos++;//扇区地址增1
			secoff=0;//偏移位置为0 	 

		   	pBuffer+=secremain;  //指针偏移
			WriteAddr+=secremain;//写地址偏移	   
		   	NumByteToWrite-=secremain;				//字节数递减
			if(NumByteToWrite>4096)secremain=4096;	//下一个扇区还是写不完
			else secremain=NumByteToWrite;			//下一个扇区可以写完了
		}	 
	};	 
}

// static void _spi_flash_Quad_Write(SPI_FLASH *spi_flash,uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)   
// { 
// 	uint32_t secpos;
// 	uint16_t secoff;
// 	uint16_t secremain;	   
//  	uint16_t i;    
// 	uint8_t * W25QXX_BUF;	  
//    	W25QXX_BUF=W25QXX_BUFFER;	     
//  	secpos=WriteAddr/4096;//扇区地址  
// 	secoff=WriteAddr%4096;//在扇区内的偏移
// 	secremain=4096-secoff;//扇区剩余空间大小   
//  	log_info("ad:%X,nb:%X\r\n",WriteAddr,NumByteToWrite);//测试用
//  	if(NumByteToWrite<=secremain)secremain=NumByteToWrite;//不大于4096个字节
// 	while(1) 
// 	{	
// 		_spi_flash_Quad_Read(W25QXX_BUF,secpos*4096,4096);//读出整个扇区的内容
// 		for(i=0;i<secremain;i++)//校验数据
// 		{
// 			if(W25QXX_BUF[secoff+i]!=0XFF)break;//需要擦除  	  
// 		}
// 		if(i<secremain)//需要擦除
// 		{
// 			_spi_flash_Erase_Sector(secpos);//擦除这个扇区
// 			for(i=0;i<secremain;i++)	   //复制
// 			{
// 				W25QXX_BUF[i+secoff]=pBuffer[i];	  
// 			}
// 			_spi_flash_Quad_Write_NoCheck(W25QXX_BUF,secpos*4096,4096);//写入整个扇区  

// 		}else _spi_flash_Quad_Write_NoCheck(pBuffer,WriteAddr,secremain);//写已经擦除了的,直接写入扇区剩余区间. 				   
// 		if(NumByteToWrite==secremain)break;//写入结束了
// 		else//写入未结束
// 		{
// 			secpos++;//扇区地址增1
// 			secoff=0;//偏移位置为0 	 

// 		   	pBuffer+=secremain;  //指针偏移
// 			WriteAddr+=secremain;//写地址偏移	   
// 		   	NumByteToWrite-=secremain;				//字节数递减
// 			if(NumByteToWrite>4096)secremain=4096;	//下一个扇区还是写不完
// 			else secremain=NumByteToWrite;			//下一个扇区可以写完了
// 		}	 
// 	};	 
// }

//擦除整个芯片		  
//等待时间超长...
static void _spi_flash_Erase_Chip(SPI_FLASH *spi_flash)   
{                                   
    _spi_flash_Write_Enable(spi_flash);                  //SET WEL 
    _spi_flash_Wait_Busy(spi_flash);   
  	spi_flash->cs.reset_bit(&spi_flash->cs);                            //使能器件   
    spi_flash->spi.readwritebyte(&spi_flash->spi,Flash_ChipErase);        //发送片擦除命令  
	spi_flash->cs.set_bit(&spi_flash->cs);                            //取消片选     	      
	_spi_flash_Wait_Busy(spi_flash);   				   //等待芯片擦除结束
}   
//擦除一个扇区
//Dst_Addr:扇区地址 根据实际容量设置
//擦除一个扇区的最少时间:150ms
static void _spi_flash_Erase_Sector(SPI_FLASH *spi_flash,uint32_t Dst_Addr)   
{  
	//监视falsh擦除情况,测试用   
 	log_info("fe:%x\r\n",Dst_Addr);	  
 	Dst_Addr*=4096;
    _spi_flash_Write_Enable(spi_flash);                  //SET WEL 	 
    _spi_flash_Wait_Busy(spi_flash);   
  	spi_flash->cs.reset_bit(&spi_flash->cs);                            //使能器件   
    spi_flash->spi.readwritebyte(&spi_flash->spi,Flash_SectorErase);   //发送扇区擦除指令 
    if(spi_flash->flash_type==W25Q256)                //如果是W25Q256的话地址为4字节的，要发送最高8位
    {
        spi_flash->spi.readwritebyte(&spi_flash->spi,(uint8_t)((Dst_Addr)>>24)); 
    }
    spi_flash->spi.readwritebyte(&spi_flash->spi,(uint8_t)((Dst_Addr)>>16));  //发送24bit地址    
    spi_flash->spi.readwritebyte(&spi_flash->spi,(uint8_t)((Dst_Addr)>>8));   
    spi_flash->spi.readwritebyte(&spi_flash->spi,(uint8_t)Dst_Addr);  
	spi_flash->cs.set_bit(&spi_flash->cs);                            //取消片选     	      
    _spi_flash_Wait_Busy(spi_flash);   				    //等待擦除完成
}  
//等待空闲
static void _spi_flash_Wait_Busy(SPI_FLASH *spi_flash)   
{   
	while((_spi_flash_ReadSR(spi_flash,1)&0x01)==0x01);   // 等待BUSY位清空
}  
//进入掉电模式
static void _spi_flash_PowerDown(SPI_FLASH *spi_flash)   
{ 
  	spi_flash->cs.reset_bit(&spi_flash->cs);                            //使能器件   
    spi_flash->spi.readwritebyte(&spi_flash->spi,Flash_PowerDown);     //发送掉电命令  
  	spi_flash->cs.set_bit(&spi_flash->cs);                            //取消片选     	      
  //  delay_us(3);                            //等待TPD  
}   
//唤醒
static void _spi_flash_WAKEUP(SPI_FLASH *spi_flash)   
{  
  	spi_flash->cs.reset_bit(&spi_flash->cs);                                //使能器件   
    spi_flash->spi.readwritebyte(&spi_flash->spi,Flash_ReleasePowerDown);  //  send Flash_PowerDown command 0xAB    
	spi_flash->cs.set_bit(&spi_flash->cs);                                //取消片选     	      
  //  delay_us(3);                                //等待TRES1
}   


SPI_FLASH new_spi_flash(uint32_t spi_gpio,uint32_t sck_pinx,\
						uint32_t miso_pinx,uint32_t mosi_pinx,uint32_t spix,\
						uint32_t cs_gpio,uint32_t cs_pinx)
{
	SPI_FLASH temp;
	temp.spi = new_spi(spi_gpio,sck_pinx,miso_pinx,mosi_pinx,spix);
	temp.cs = new_outport(cs_gpio,cs_pinx);
	temp.Init = _spi_flash_Init;
	temp.ReadID = _spi_flash_ReadID;
	temp.Read = _spi_flash_Read;
	temp.Write = _spi_flash_Write;
	temp.Erase_Chip = _spi_flash_Erase_Chip;
	temp.Erase_Sector = _spi_flash_Erase_Sector;
	temp.PowerDown = _spi_flash_PowerDown;
	temp.WakeUp = _spi_flash_WAKEUP;
	temp.Init(&temp);
	return temp;
}
#endif
